import re
import os
import sublime
import sublime_plugin
def get_syntax_dir():
  pkgDir=sublime.packages_path() # 获取Packages目录
  staxDir=os.path.join(pkgDir, "KuaiJiSyntaxes") # 组合出Packages/KuaiJisyntaxes目录，用于存放自定义的syntax文件
  if not os.path.isdir(staxDir):
    # 如果Packages/KuaiJisyntaxes目录不存在
    # 则新建一个
    os.mkdir(staxDir)

  return staxDir


class Test4Command(sublime_plugin.WindowCommand):
  def run(self):
    # template是syntax文件模板内容，用于初始化新建的syntax文件
    template=r'''%YAML 1.2
---
file_extensions:

scope: string source

variables:
  wordprefix: '(?<![A-Za-z])'
  wordsufix: '(?![A-Za-z])'
  identifier: '{{wordprefix}}[A-z_][A-z0-9_]*{{wordsufix}}'
  argsufix: '[''"A-z0-9\[\]<> ,{}*=_-]*\)'

  commonkey: 'import|for|while|if|else|elif|continue|break|switch|case|default|goto|return'
  commonopr: 'and|or|is|not|in'
  commonsymopr: '[-=+*/%&|^]'
  commonlimit: 'static|global|local|public|protected|private'
  commonred: 'TRUE|FALSE|NONE|NULL?|[Tt]rue|[Ff]alse|[Nn]one|[Nn]ull?|[Nn]il|self|cls|iota'
  commontype: 'bool|u?int|double|float|long|short|char|str|(?:un)?signed|void'
  commonfunction: 'main|[Ss]?print(?:f|(?:ln))?|[Pp]rint(?:f|(?:ln))?'


  platkey: 'var|const|class|def|func(?:tion)?|type'

  platname: '[Cc](lang)?|[Gg]o(lang)?|[Pp]ython|JAVA|[Jj]ava([Ss]cript)?|JS|[Jj]s|JSON|[Jj]son|XML|[Xx]ml|HTML|[Hh]tml|YAML|[Yy]aml|HTTPS?|[Hh]ttps?|[Gg]it'

  plattype: ''

  platfunction: ''


  mudule: ''
  property: ''

  class: ''
  instance: ''


  term: ''




contexts:
  main:
    - match: '^\.+[^.].*:$'
      scope: invalid.deprecated invalid.illegal
    - match: '^-.*:$'
      scope: storage
      push: list
    - match: '^=.*:$'
      scope: markup.bold markup.italic storage
    - include: quot
    - include: keywords


  list:
    - match: '^([0-9]+ )?([^ :]*:)[^:]'
      captures:
        1: constant.numeric
        2: diff.inserted comment
    - match: '(^ +)([^:]*)(:)[^:]'
      scope: comment
      captures:
        2: markup.raw
    - match: '^[^:]+::'
      scope: diff.deleted.char comment
    - match: '^$'
      pop: true
    - include: quot
    - include: keywords


  quot:
    - match: '`[^`]*`'
      scope: comment markup.raw.title
    - match: '^!: '
      scope: invalid.illegal.emphasize


  keywords:
    - match: '([0-9]+.[0-9]+)|[0-9]+'
      scope: constant.numeric


    - match: '{{wordprefix}}(?:{{commonkey}}){{wordsufix}}'
      scope: keyword.commonkey
    - match: '{{commonsymopr}}|{{wordprefix}}(?:{{commonopr}}){{wordsufix}}'
      scope: keyword.operator.commonopr

    - match: '{{wordprefix}}(?:{{commonlimit}}){{wordsufix}}'
      scope: storage.modifier.commonlimit
    - match: '{{wordprefix}}(?:{{commonred}}){{wordsufix}}'
      scope: constant.language.commonred variable.language.commonred
    - match: '{{wordprefix}}(?:{{commontype}}){{wordsufix}}'
      scope: variable.function.commontype variable.annotation.commontype
    - match: '{{wordprefix}}(?:{{commonfunction}}){{wordsufix}}'
      scope: entity.name.function.commonfunction


    - match: '{{wordprefix}}(?:{{platkey}}){{wordsufix}}'
      scope: storage.type.platkey
    - match: '{{wordprefix}}(?:{{platname}}){{wordsufix}}'
      scope: punctuation.section.platname
    - match: '{{wordprefix}}(?:{{plattype}}){{wordsufix}}'
      scope: support.type.plattype
    - match: '{{wordprefix}}(?:{{platfunction}}){{wordsufix}}'
      scope: markup.italic entity.name.function.platfunction


    - match: '{{wordprefix}}(?:{{mudule}}){{wordsufix}}'
      scope: punctuation.section.mudule
    - match: '{{wordprefix}}(?:{{property}}){{wordsufix}}'
      scope: punctuation.section.property markup.italic

    - match: '{{wordprefix}}(?:{{class}}){{wordsufix}}'
      scope: entity.name.class
    - match: '{{wordprefix}}(?:{{instance}}){{wordsufix}}'
      scope: entity.name.class.instance markup.italic


    - match: '\b[rR]?[bBuU]?(?=[''"])'
      scope: storage.type.string

    - match: '{{wordprefix}}(?:{{term}}){{wordsufix}}'
      scope: support.type.property-name.term'''
    # 文件名输入面板的回调函数
    def get_file_name(iptFleNam):
      # timeout的回调函数，每隔1毫秒判断一次staxVew的buffer是否准备就绪，是则调用edit_file_after_load命令进行编辑；
      # 否则循环设置timeout；
      # 因为ST3限制了TextCommand的run(self, edit)方法结束后就不能再用它的edit参数来编辑view内容；
      # 所以要用timeout来等待buffer准备就绪，再调用一个TextCommand来编辑staxVew内容。
      def wait():
        if staxVew.is_loading():
          sublime.set_timeout(wait, 1)
        else:
          staxVew.run_command("custom_syntax_insert_content", {"insertions": [(0, template)]})
          # timeout的回调函数wait()结束


      # 扩展名输入面板的回调函数get_ext_name()
      def get_ext_name(iptExNam):
        scpPt=staxVew.find(r'^scope: string source$', 0).end()
        exPt=staxVew.find(r'^file_extensions:$', 0).end()
        staxVew.run_command("custom_syntax_insert_content", {"insertions": [(scpPt, '.'+iptExNam), (exPt, "\n  - "+iptExNam)]})


      # get_file_name()回调函数正文
      staxPath=os.path.join(staxDir, iptFleNam) # 将用户输入的文件名和Packages/KuaiJisyntaxes目录组合成完整的长文件名
      if os.path.isfile(staxPath):
        # 如果文件已存在，则弹窗提示并结束
        sublime.message_dialog("文件名已存在！")
      else:
        # 如果文件不存在，则打开一个指向它的view：staxVew
        # 编辑完成后保存，就会新建一个对应的文件
        staxVew=self.window.open_file(staxPath)
        sublime.set_timeout(wait, 1) # 打开staxVew后，要设置timeout等待它的buffer准备就绪，才能编辑它的内容
        self.window.show_input_panel("请输入扩展名：", "", get_ext_name, None, None) # get_file_name()回调函数的最后，弹出扩展名输入面板，请求用户输入扩展名
          # get_file_name()回调函数结束




    # run()方法的正文开始
    staxDir=get_syntax_dir() # 获取存放syntax文件的目录
    if not os.path.isdir(staxDir):
      # 如果syntax目录不存在
      # 则新建一个
      os.mkdir(staxDir)

    # 弹出文件名输入面板，请求用户输入文件名
    self.window.show_input_panel("请输入文件名：", ".sublime-syntax", get_file_name, None, None)






# 专门用来向view中插入内容的命令，因为ST3限制TextCommand的run()方法结束后就不能再编辑view内容；
# 所以回调函数想要编辑view内容，只能再调用一个TextCommand
# run()方法的pt参数是插入位置，cotnt参数是插入内容
class CustomSyntaxInsertContentCommand(sublime_plugin.TextCommand):
  def run(self, edit, insertions):
    self.view.set_read_only(False) # 插入内容前解除view的只读模式
    for ins in insertions:
      self.view.insert(edit, ins[0], ins[1])

    self.view.set_read_only(True) # 插入内容完毕后重新将view设为只读，防止用户直接编辑syntax文件内容



class Test5Command(sublime_plugin.WindowCommand):
  def run(self):
    def on_select(idx):
      staxPath=os.path.join(staxDir, stax_lst[idx])
      staxVew=self.window.open_file(staxPath)


    vew=self.window.active_view()
    if re.search(r'([/\\])Packages\1KuaiJiSyntaxes\1test\.sublime-syntax$', vew.file_name()):
      staxVew=vew
    else:
      staxDir=get_syntax_dir()
      stax_lst=os.listdir(staxDir)
      self.window.show_quick_panel(stax_lst, on_select)

    
